import 'package:avd_sdk_plugin/avd_message.dart';
import 'package:avd_sdk_plugin/avd_room_info.dart';
import 'package:avd_sdk_plugin/avd_user.dart';
import 'package:avd_sdk_plugin/rtc_video_render.dart';
import 'avd_message.dart';
import 'method_key.dart';
import 'package:flutter/services.dart';


class AvdSdkPlugin {
  static final  MethodChannel methodChannel =  const MethodChannel('avd_sdk_plugin');

  static Future<T?> _invokeMethod<T>(String method,
      [Map<String, dynamic>? arguments]) {
    return methodChannel.invokeMethod(method, arguments);
  }

  Future<String?> getPlatformVersion() async {
    final version = await methodChannel.invokeMethod<String>('getPlatformVersion');
    return version;
  }



  ///初始化 SDK
  ///[url] 音视频服务器地址
  ///[appkey] appkey
  ///[secretKey] secretKey
  static Future<void> init(String? url,String? appKey,String? secretKey) async {
    _addNativeMethodCallHandler();
    await _invokeMethod(AVDMethod.init,{
      'url':url,
      'appKey':appKey,
      'secretKey':secretKey});
  }

  ///获取sdk版本
  static Future<String?> getVersion() async{
    return _invokeMethod(AVDMethod.getVersion);
  }

  ///创建一个房间
  ///[roomInfo]房间信息对象
  ///返回错误码
  static Future<void> scheduleRoom(AVDRoomInfo roomInfo) async{
    await _invokeMethod(AVDMethod.scheduleRoom,{
      'roomId':roomInfo.roomId,
      'roomName':roomInfo.roomName,
      'roomTopic':roomInfo.roomTopic,
      'owerId':roomInfo.owerId,
    });
  }

  ///设置日志等级以及路径
  ///[parms] [sensitive verbose info warning error none ] ;[debug]是否在调试输出；两个值时中间空格分隔
  ///[path] 日志文件名，若无日志文件名，则不写文件。
  static Future<void> setLogParams(String parms,String path) async{
    await _invokeMethod(AVDMethod.setLogParams,{
      'parms':parms,
      'path':path,
    });
  }


  ///加入房间
  ///[roomId] 房间号
  ///[userId] 用户id
  ///[userName] 用户名称
  ///[userData] 用户扩展字段
  static Future<void> joinRoom(String? roomId,String? userId,String? userName,String userData) async{
    await _invokeMethod(AVDMethod.joinRoom,{
      'roomId':roomId,
      'userId':userId,
      'userName':userName,
      'userData':userData});
  }

  ///离开房间
  static Future<void> leaveRoom() async{
    await _invokeMethod(AVDMethod.leaveRoom);
  }

  ///关闭房间房间其他人都会被踢出
  static Future<void> closeRoom() async{
    await _invokeMethod(AVDMethod.closeRoom);
  }

  ///发布本地摄像头
  static Future<void> publishCamera() async{
    await _invokeMethod(AVDMethod.publishCamera);
  }

  ///取消发布本地摄像头
  static Future<void> unpublishCamera() async{
    await _invokeMethod(AVDMethod.unpublishCamera);
  }

  ///切换本地摄像头
  static Future<void> switchCamera() async{
    await _invokeMethod(AVDMethod.switchToLocalCamera);
  }


  /// subscribe and publish list
  /// 订阅摄像头视频
  /// [deviceid] 摄像头Id，唯一标示一路摄像头视频。
  ///@return 返回错误代码。
  /// @note 订阅操作为异步操作，操作结果在 onSubscribeResult 中返回。
  /// @sa onSubscribeResult
  static Future<void> subscribe(String deviceid) async{
    await _invokeMethod(AVDMethod.subscribe,{
      'deviceid':deviceid
    });
  }

  /// 取消订阅摄像头视频
  /// [deviceid] 摄像头Id，唯一标示一路摄像头视频。
  ///@return 返回错误代码。
  /// @note 取消订阅操作为异步操作，操作结果在 onUnsubscribeResult 中返回。
  /// @sa onUnsubscribeResult
  static Future<void> unsubscribe(String deviceid) async{
    await _invokeMethod(AVDMethod.unsubscribe,{
      'deviceid':deviceid
    });
  }

  ///指定render渲染视频
  ///[deviceid]摄像头id
  ///[render]视频需要渲染到那个窗口
  ///return 返回错误代码
  static Future<int> attachRenderWithDeviceId(String deviceid,RTCVideoRender render) async{
    return  await _invokeMethod(AVDMethod.attachRenderWithDeviceId,{
      'deviceid':deviceid,
      'tagId':render.tagId
    });
  }

  ///取消指定render渲染视频
  ///[deviceid]摄像头id
  ///[render]视频需要渲染到那个窗口
 ///return 返回错误代码
  static Future<int> detachRenderWithDeviceId(String deviceid,RTCVideoRender render) async{
    return  await _invokeMethod(AVDMethod.detachRenderWithDeviceId,{
      'deviceid':deviceid,
      'tagId':render.tagId
    });
  }

  ///打开本地麦克风
  static Future<void> openMicrophone() async{
    await _invokeMethod(AVDMethod.openMicrophone);
  }

  ///打开本地麦克风
  static Future<void> closeMicrophone() async{
    await _invokeMethod(AVDMethod.closeMicrophone);
  }

  ///获取房间已经发布的摄像头列表
  ///[publishedCameraList]存放已经发布的摄像头id列表
  ///
  static Future<void> getPublishedCameras(Function(List publishedCameraList)? finished) async{
    Map resultMap = await _invokeMethod(AVDMethod.getPublishedCameras);
    List? coversationList = resultMap["publishedCameraList"];
    List cameraList = [];
    if (coversationList != null) {
      for (String deviceid in coversationList) {
        cameraList.add(deviceid);
      }
    }
    if (finished != null) {
      finished(cameraList);
    }
  }

  ///设置耳麦模式
  ///0 外放 1 耳麦
  static Future<void> setSpeakerMode(int value) async{
    await _invokeMethod(AVDMethod.setSpeakerMode,{
      'modelValue':value
    });
  }

  ///发送公聊消息
  ///[msg] 消息内容
  static Future<void> sendPublicMessage(String msg) async{
    await _invokeMethod(AVDMethod.sendPublicMessage,{
      'msg':msg,
    });
  }

  ///发送私聊消息
  ///[uid]接收方uid
  ///[msg]消息内容
  static Future<void> sendPrivateMessage(String msg,String uid) async{
    await _invokeMethod(AVDMethod.sendPrivateMessage,{
      'msg':msg,
      'uid':uid
    });
  }

  ///发布屏幕共享
  static Future<void> publishScreen() async{
    await _invokeMethod(AVDMethod.publishScreen);
  }

  ///停止屏幕共享
  static Future<void> unpublishScreen() async{
    await _invokeMethod(AVDMethod.unpublishScreen);
  }



  ///Native CallBack
  ///叁体sdk初始化回调
  ///[result]错误码 0表示成功 非0表示失败具体错误对照在线的错误码对照表
  static Function(int result)? onInitResult;
  ///加入房间回调
 ///[result]错误码 0表示成功 非0表示失败具体错误对照在线的错误码对照表
  static Function(int result)? onJoinResult;
  ///加入房间回调
  ///[result]错误码 0表示成功 非0表示失败具体错误对照在线的错误码对照表
  static Function(int result, String roomId)? onScheduleRoomResult;

  //video
  ///发布自己视频回调
  static Function(String deviceid)? onPublishLocalResult;
  ///取消发布自己视频回调
  static Function(String deviceid)? onUnpublishLocalResult;
  ///别人与自己发布/打开摄像头回调
  static Function(String deviceid)? onPublishCameraNotify;
  ///别人取消发布/关闭摄像头回调
  static Function(String deviceid)? onUnpublishCameraNotify;

  //chat
  ///接收到公共消息回调
  ///[msg] msg对象
  static Function(AVDMessage msg)? onPublicMessage;
  ///接收到私聊消息回调
  ///[msg] msg对象
  static Function(AVDMessage msg)? onPrivateMessage;

  //user
  ///房间有新用户加入时回调
  ///[user] user对象
  static Function(AVDUser user)? onUserJoinNotify;

  ///房间有用户离开时回调
  ///[user] user对象
  ///[reason] 原因 具体对照在线的错误码对照表
  static Function(AVDUser user, int reason)? onUserLeaveNotify;

  //screen
  ///房间用户发布屏幕共享回调
  ///[deviceid]设备id
  static Function(String deviceid)? onPublishScreenNotify;
  ///房间用户取消发布屏幕共享回调
  ///[deviceid]设备id
  static Function(String deviceid)? onUnpublishScreenNotify;
  ///房间有其他用户发布屏幕共享回调
  ///[deviceid]设备id
  ///[result]错误码 0表示成功 非0表示失败具体错误对照在线的错误码对照表
  static Function(String deviceid, int result)? onSubscribeScreenResult;
  ///房间有其他用户发布屏幕共享回调
  ///[deviceid]设备id
  ///[result]错误码 0表示成功 非0表示失败具体错误对照在线的错误码对照表
  static Function(String deviceid,int result)? onUnsubscribeScreenResult;


  ///native回调监听
  static void _addNativeMethodCallHandler() {
    methodChannel.setMethodCallHandler(_methodCallHandler);
  }

  static Future<dynamic> _methodCallHandler(MethodCall call) async {

    switch (call.method) {

      case AVDMethodCallBack.onInitResult:{
        if (onInitResult != null) {
          int result = call.arguments;
          onInitResult!(result);
        }
      }
      break;

      case AVDMethodCallBack.onJoinResult:{
        if (onJoinResult != null) {
          int result = call.arguments;
          onJoinResult!(result);
        }
      }
      break;

      case AVDMethodCallBack.onPublishLocalResult:{
        if (onPublishLocalResult != null) {
          String deviceid = call.arguments;
          onPublishLocalResult!(deviceid);
        }
      }
      break;

      case AVDMethodCallBack.onUnpublishLocalResult:{
        if (onUnpublishLocalResult != null) {
          String deviceid = call.arguments;
          onUnpublishLocalResult!(deviceid);
        }
      }
      break;

      case AVDMethodCallBack.onPublishCameraNotify:{
        if (onPublishCameraNotify != null) {
          String deviceid = call.arguments;
          onPublishCameraNotify!(deviceid);
        }
      }
      break;

      case AVDMethodCallBack.onUnpublishCameraNotify:{
        if (onUnpublishCameraNotify != null) {
          String deviceid = call.arguments;
          onUnpublishCameraNotify!(deviceid);
        }
      }
      break;

      case AVDMethodCallBack.onPublicMessage:{
        if (onPublicMessage != null) {
          AVDMessage msg =  AVDMessage();
          Map map = call.arguments;
          msg.decode(map);
          onPublicMessage!(msg);
        }
      }
      break;

      case AVDMethodCallBack.onPrivateMessage:{
        if (onPrivateMessage != null) {
          AVDMessage msg =  AVDMessage();
          Map map = call.arguments;
          msg.decode(map);
          onPrivateMessage!(msg);
        }
      }
      break;

      case AVDMethodCallBack.onUserJoinNotify:{
        if (onUserJoinNotify != null) {
          AVDUser user =  AVDUser();
          Map map = call.arguments;
          user.decode(map);
          onUserJoinNotify!(user);
        }
      }
      break;

      case AVDMethodCallBack.onUserLeaveNotify:{
        if (onUserLeaveNotify != null) {
          AVDUser user =  AVDUser();
          Map map = call.arguments;
          user.decode(map);
          onUserLeaveNotify!(user,map["reason"]);
        }
      }
      break;

      case AVDMethodCallBack.onPublishScreenNotify:{
        if (onPublishScreenNotify != null) {
          String deviceid = call.arguments;
          onPublishScreenNotify!(deviceid);
        }
      }
      break;

      case AVDMethodCallBack.onUnpublishScreenNotify:{
        if (onUnpublishScreenNotify != null) {
          String deviceid = call.arguments;
          onUnpublishScreenNotify!(deviceid);
        }
      }
      break;

      case AVDMethodCallBack.onSubscribeScreenResult:{
        if (onSubscribeScreenResult != null) {
          Map map  = call.arguments;
          onSubscribeScreenResult!(map["deviceid"],map["result"]);
        }
      }
      break;

      case AVDMethodCallBack.onUnsubscribeScreenResult:{
        if (onUnsubscribeScreenResult != null) {
          Map map  = call.arguments;
          onUnsubscribeScreenResult!(map["deviceid"],map["result"]);
        }
      }
      break;

      case AVDMethodCallBack.onScheduleRoomResult:{
        if (onScheduleRoomResult != null) {
          Map map  = call.arguments;
          onScheduleRoomResult!(map["result"],map["roomId"]);
        }
      }
      break;


    }

  }
}
